"""版本下载"""

import requests
import os
import threading
import json
from contextlib import closing

from core import settings
from core import tools
from core import logs

def download_json(path, version):
    logs.log("INFO","start download ["+version+"] json","DOWNLOAD")
    url=tools.render_str(settings.VERSION_API,version=version,type="json")
    get_req=requests.get(url)
    get_req.encoding = 'utf-8'
    get_json=get_req.text
    with open(path+version+".json","w",encoding="utf-8") as file:
        file.write(get_json)
    logs.log("INFO","download ["+version+"] json end","DOWNLOAD")
    return get_json

def download_ass_index(path, game_path, version):
    logs.log("INFO","start download ["+version+"] ass index","DOWNLOAD")
    with open(game_path+version+".json","r",encoding="utf-8") as file:
        get_json = json.loads(file.read())
    index_url=get_json["assetIndex"]["url"]
    index_file_path = path + "assets/indexes/" + version + ".json"
    get_req=requests.get(index_url)
    get_req.encoding = 'utf-8'
    get_json=get_req.text
    with open(index_file_path,"w",encoding="utf-8") as file:
        file.write(get_json)
    logs.log("INFO","download ["+version+"] ass end","DOWNLOAD")
    return get_json

def download_ass_hash(path,this_hash):
    logs.log("INFO","download ass hash ["+this_hash+"]","DOWNLOAD")
    url=tools.render_str(settings.VERSION_API,two_hash=this_hash[:2],hash=this_hash)
    file_path = path + "assets/objects/" + this_hash[:2] + "/" + this_hash
    for i in range(settings.RETRY):
        try:
            get_req=requests.get(url)
            get_ass=get_req.content
        except:
            logs.log("WARNING","download ass hash again ["+this_hash+"]","DOWNLOAD")
        else:
            break
    if not os.path.exists(path + "assets/objects/" + this_hash[:2] + "/"):
        try:
            os.makedirs(path + "assets/objects/" + this_hash[:2] + "/")
        except:
            logs.log("WARNING","download ass hash mkdir ["+this_hash[:2]+"] error","DOWNLOAD")
    with open(file_path,"wb") as file:
        file.write(get_ass)

def download_ass_file(path, ass_tool, assindex):
    ass_num=0
    ass_path=path
    obj_list=[]
    for info in assindex["objects"].values():
        obj_list.append(info)
    ass_sum=len(obj_list)
    
    def subtask(*args,**kwargs):
        nonlocal ass_num, ass_sum, ass_path
        while(len(obj_list)>0):
            info=obj_list.pop(0)
            this_hash=info["hash"]
            download_ass_hash(ass_path, this_hash)
            ass_num+=1
            ass_tool.set_progress(int(ass_num/ass_sum*100))
    class downloadThread (threading.Thread):   #继承父类threading.Thread
        def __init__(self, threadID, name, counter):
            threading.Thread.__init__(self)
            self.threadID = threadID
            self.name = name
            self.counter = counter
        def run(self): 
            logs.log("INFO","thread start ["+str(self.counter)+"]","DOWNLOAD")
            subtask()
            logs.log("INFO","thread stop ["+str(self.counter)+"]","DOWNLOAD")
    thread_pool=[]
    for thread_num in range(1,settings.THREAD_NUM+1):
        thread_pool.append(downloadThread(thread_num+1, "downloadThread"+str(thread_num), thread_num))
        thread_pool[-1].start()
    while(ass_num!=ass_sum):
        pass
    
def download_lib_file(path, lib_tool, lib_json_list):
    lib_num=0
    lib_path=path+"libraries/"
    lib_list=[]
    for this_list in lib_json_list["libraries"]:
        lib_list.append(this_list)
    lib_sum=len(lib_list)
    def subtask(*args,**kwargs):
        nonlocal lib_num, lib_sum, lib_path
        while(len(lib_list)>0):
            info=lib_list.pop(0)
            logs.log("INFO","download lib ["+info["name"]+"] start","DOWNLOAD")
            if "artifact" in info["downloads"]:
                this_path=lib_path+info["downloads"]["artifact"]["path"]
                get_url=info["downloads"]["artifact"]["url"]
                get_url = get_url.replace("https://libraries.minecraft.net/", "")
                get_url = get_url.replace("http://libraries.minecraft.net/", "")
                this_url = tools.render_str(settings.LIB_API,reqlist=get_url)
                for i in range(settings.RETRY):
                    try:
                        lib_req = requests.get(this_url)
                        get_lib=lib_req.content
                    except:
                        logs.log("WARNING","download lib again ["+info["name"]+"]","DOWNLOAD")
                    else:
                        break
                else:
                    logs.log("WARNING", "download lib error ["+info["name"]+"]", "DOWNLOAD")
                    raise
                if not (os.path.exists(os.path.split(this_path)[0])):
                    os.makedirs(os.path.split(this_path)[0])
                with open(this_path,"wb") as file:
                    file.write(get_lib)
            if "classifiers" in info["downloads"]:
                if ("natives-"+settings.PC_OS) in info["downloads"]["classifiers"]:
                    this_path=lib_path+info["downloads"]["classifiers"][("natives-"+settings.PC_OS)]["path"]
                    this_url=info["downloads"]["classifiers"][("natives-"+settings.PC_OS)]["url"]
                    for i in range(settings.RETRY):
                        try:
                            lib_req = requests.get(this_url)
                            get_lib=lib_req.content
                        except:
                            logs.log("WARNING","download lib again ["+info["name"]+"]","DOWNLOAD")
                        else:
                            break
                    else:
                        logs.log("WARNING", "download lib error ["+info["name"]+"]", "DOWNLOAD")
                        raise
                    if not (os.path.exists(os.path.split(this_path)[0])):
                        os.makedirs(os.path.split(this_path)[0])
                    with open(this_path,"wb") as file:
                        file.write(get_lib)
                if ("natives-"+settings.PC_OS+"-"+settings.ARCH) in info["downloads"]["classifiers"]:
                    this_path=lib_path+info["downloads"]["classifiers"][("natives-"+settings.PC_OS+"-"+settings.ARCH)]["path"]
                    this_url=info["downloads"]["classifiers"][("natives-"+settings.PC_OS+"-"+settings.ARCH)]["url"]
                    for i in range(settings.RETRY):
                        try:
                            lib_req = requests.get(this_url)
                            get_lib=lib_req.content
                        except:
                            logs.log("WARNING","download lib again ["+info["name"]+"]","DOWNLOAD")
                        else:
                            break
                    if not (os.path.exists(os.path.split(this_path)[0])):
                        os.makedirs(os.path.split(this_path)[0])
                    with open(this_path,"wb") as file:
                        file.write(get_lib)
            #logs.log("INFO","download lib ["+info+"]","DOWNLOAD")
            #download_ss_hash(ass_path, this_hash)
            lib_num+=1
            lib_tool.set_progress(int(lib_num/lib_sum*100))
    class downloadThread (threading.Thread):   #继承父类threading.Thread
        def __init__(self, threadID, name, counter):
            threading.Thread.__init__(self)
            self.threadID = threadID
            self.name = name
            self.counter = counter
        def run(self): 
            logs.log("INFO","thread start ["+str(self.counter)+"]","DOWNLOAD")
            subtask()
            logs.log("INFO","thread stop ["+str(self.counter)+"]","DOWNLOAD")
    thread_pool=[]
    for thread_num in range(1,settings.THREAD_NUM+1):
        thread_pool.append(downloadThread(thread_num+1, "downloadThread"+str(thread_num), thread_num))
        thread_pool[-1].start()
    while(lib_num!=lib_sum):
        pass

def download_main_jar(path,tool,name,version):
    logs.log("INFO","start download ["+version+"] main jar","DOWNLOAD")
    url=tools.render_str(settings.VERSION_API,version=version,type="client")
    for i in range(settings.RETRY):
        try:
            this_get=requests.get(url,stream=True)
        except:
            logs.log("WARNING","download main jar again ["+version+"]","DOWNLOAD")
        else:
            break
    else:
        raise
    file_name=path+"version/"+name+"/"+version+".jar"
    with closing(this_get) as response:
        content_size = int(response.headers['content-length'])
        content_sum=0
        with open(file_name, "wb") as file:
            for data in response.iter_content(chunk_size=settings.CHUNK_SIZE):
                file.write(data)
                content_sum+=len(data)
                tool.set_progress(int(content_sum/content_size*100))
    logs.log("INFO","download ["+version+"] main jar stop","DOWNLOAD")


